package com
{
	import com.protocols.Mod;
	import com.utils.Utils;
	
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;

	/**
	 * ...
	 * @author Liseen
	 */
	public class Protocol 
	{
		private static var _wired:Dictionary;
		public static var modName:String;
        public static var funName:String;
		public function Protocol() 
		{
			
		}
		
		public static function init():void 
		{
			if (_wired == null) {
				_wired = new Dictionary();
			}
		}
		
		public static function addWired(_arg1:Object):void
        {
            var _local2:int = _arg1["module"];
            var _local3:int = _arg1["action"];
            _wired[concat(_local2, _local3)] = true;
        }
		
		public static function removeWired(_arg1:int, _arg2:int):void
        {
            var _local3:String = concat(_arg1, _arg2);
            if (_wired[_local3])
            {
                delete _wired[_local3];
            }
        }
		
		public static function keepAlive(_arg1:int, _arg2:int):Boolean
        {
            return (!(!(_wired[concat(_arg1, _arg2)])));
        }
		
		public static function concat(_arg1:int, _arg2:int):String
        {
            return ([_arg1, "-", _arg2].join(""));
        }
		
		public static function synthesize(_arg1:Array, _arg2:Array):ByteArray
        {
            return (writeArray(_arg1, _arg2, true));
        }
		
		public static function analyze(_arg1:ByteArray, _arg2:Array):Array
        {
            var _local3:Array = readArray(_arg1, _arg2);
            return (_local3);
        }
		
		private static function readArray(_arg1:ByteArray, _arg2:Array):Array
        {
            var _local6:int;
            var _local7:uint;
            var _local8:Number;
            var _local9:Array;
            var _local10:uint;
            var _local11:int;
            var _local3:Array = [];
            var _local4:uint = _arg2.length;
            var _local5:uint;
            while (_local5 < _local4)
            {
                switch (_arg2[_local5])
                {
                    case Utils.BooleanUtil:
                        _local3.push(_arg1.readBoolean());
                        break;
                    case Utils.ByteUtil:
                        _local3.push(_arg1.readByte());
                        break;
                    case Utils.DoubleUtil:
                        _local3.push(_arg1.readDouble());
                        break;
                    case Utils.LongUtil:
                        _local6 = _arg1.readInt();
                        _local7 = _arg1.readUnsignedInt();
                        _local8 = ((_local6 * Math.pow(2, 32)) + _local7);
                        _local3.push(_local8);
                        break;
                    case Utils.FloatUtil:
                        _local3.push(_arg1.readFloat());
                        break;
                    case Utils.IntUtil:
                        _local3.push(_arg1.readInt());
                        break;
                    case Utils.ShortUtil:
                        _local3.push(_arg1.readShort());
                        break;
                    case Utils.StringUtil:
                        _local3.push(_arg1.readUTF());
                        break;
                    default:
                        if ((_arg2[_local5] is Array))
                        {
                            _local9 = [];
                            _local10 = _arg1.readUnsignedShort();
                            _local11 = 0;
                            while (_local11 < _local10)
                            {
                                _local9[_local11] = readArray(_arg1, _arg2[_local5]);
                                _local11++;
                            }
                            _local3.push(_local9);
                        }
                }
                _local5++;
            }
            return (_local3);
        }
		
		private static function writeArray(_arg1:Array, _arg2:Array, _arg3:Boolean=false):ByteArray
        {
            var _local6:uint;
            var _local8:String;
            var _local9:uint;
            var _local10:uint;
            var _local11:int;
            var _local12:int;
            var _local13:ByteArray;
            var _local4:ByteArray = new ByteArray();
            var _local5:uint = _arg2.length;
            if (_arg1.length != _local5)
            {
                _local8 = ("[request]接口不匹配：" + getProtocolDescription(_arg2));
                throw (new Error(_local8));
            }
            _local6 = 0;
            while (_local6 < _local5)
            {
                switch (_arg2[_local6])
                {
                    case Utils.BooleanUtil:
                        _local4.writeBoolean(_arg1[_local6]);
                        break;
                    case Utils.ByteUtil:
                        _local4.writeByte(_arg1[_local6]);
                        break;
                    case Utils.DoubleUtil:
                        _local4.writeDouble(_arg1[_local6]);
                        break;
                    case Utils.LongUtil:
                        _local9 = (_arg1[_local6] / Math.pow(2, 32));
                        _local10 = (_arg1[_local6] % Math.pow(2, 32));
                        _local4.writeUnsignedInt(_local9);
                        _local4.writeUnsignedInt(_local10);
                        break;
                    case Utils.FloatUtil:
                        _local4.writeFloat(_arg1[_local6]);
                        break;
                    case Utils.IntUtil:
                        _local4.writeInt(_arg1[_local6]);
                        break;
                    case Utils.ShortUtil:
                        _local4.writeShort(_arg1[_local6]);
                        break;
                    case Utils.StringUtil:
                        _local4.writeUTF(_arg1[_local6]);
                        break;
                    default:
                        if ((_arg2[_local6] is Array))
                        {
                            _local11 = _arg1[_local6].length;
                            _local4.writeShort(_local11);
                            _local12 = 0;
                            while (_local12 < _local11)
                            {
                                _local13 = writeArray(_arg1[_local6][_local12], _arg2[_local6], true);
                                _local4.writeBytes(_local13, 0, _local13.length);
                                _local12++;
                            }
                        }
                }
                _local6++;
            }
            var _local7:ByteArray = new ByteArray();
            if (_arg3 == false)
            {
                _local7.writeShort(_local4.length);
            }
            _local7.writeBytes(_local4, 0, _local4.length);
            return (_local7);
        }
		
		public static function lookupProtocol(_module:int, _act:int):Object
        {
            var _moduleID:String;
            var _actionsInModule:Object;
            var _actions:Array;
            var _actSize:int;
            var _actIndex:int;
            var _actObj:Object;
            var _returnObj:Object = {};
            for (_moduleID in Mod.Modules)
            {
                if (parseInt(_moduleID) == _module)
                {
                    _actionsInModule = Mod.Modules[_moduleID];
                    _actions = _actionsInModule["Actions"];
                    _actSize = _actions.length;
                    _actIndex = 0;
                    while (_actIndex < _actSize)
                    {
                        _actObj = _actionsInModule[_actions[_actIndex]];
                        if (_actObj["action"] == _act)
                        {
                            _returnObj = _actObj;
                            break;
                        }
                        _actIndex++;
                    }
                    break;
                }
            }
            return (_returnObj);
        }
		
		/**
		 * 
		 * 协议描述
		 * 
		 * @param _requestParams 协议请求参数类型
		 * 
		 * 
		 */
		public static function getProtocolDescription(_requestParams:Array):String
        {
            var _moduleID:String;
            var _module:Class;
            var _actionNames:Array;
            var _actionNameSize:int;
            var _actNameIndex:int;
            var _act:Object;
            var _protocalDesc:String = "";
            for (_moduleID in Mod.Modules)
            {
                _module = Mod.Modules[_moduleID];
                _actionNames = _module["Actions"];
                _actionNameSize = _actionNames.length;
                _actNameIndex = 0;
                while (_actNameIndex < _actionNameSize)
                {
                    _act = _module[_actionNames[_actNameIndex]];
                    if (_act["request"] == _requestParams)
                    {
                        modName = (_module + "").replace(/^\[class |\]$/g, "");
                        funName = _actionNames[_actNameIndex];
                        _protocalDesc = [modName, "(module:", _act["module"], ")", ", ", funName, "(action:", _act["action"], ")"].join("");
                        break;
                    }
                    _actNameIndex++;
                }
            }
            return (_protocalDesc);
        }
		
	}
	Protocol.init();
}